﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using PloobsEngine.Utils;
using PloobsEngine.Modelo.Animation;
using PloobsEngine.SceneControl;
using PloobsEngine.Light;
using PloobsEngine.Modelo;
using PloobsEngine.Cameras;

namespace PloobsEngine.Material
{
    /// <summary>
    /// Shader que simula objetos piscando.
    /// (Pisca entre Cor da textura e cor final)
    /// </summary>
    public class BlinkDeferred : IShader
    {
        private Effect _shader;
        private float specularIntensity = 0.1f;
        private Color finalColor;
        private float interpolator;
        
        Random rd = new Random();

        /// <summary>
        /// Cor final (Pisca entre Cor da textura e cor final)
        /// </summary>
        public Color FinalColor
        {
            get { return finalColor; }
            set { finalColor = value; }
        }

        public float SpecularIntensity
        {
            get { return specularIntensity; }
            set { specularIntensity = value; }
        }
        private float specularPower = 0.1f;

        public float SpecularPower
        {
            get { return specularPower; }
            set { specularPower = value; }
        }

        public override MaterialType MaterialType
        {
            get { return MaterialType.DEFERRED; }
        }

        private float speedMultipler = 1;

        /// <summary>
        /// Controla a velocidade do piscamento
        /// default 1
        /// </summary>
        public float SpeedMultipler
        {
            get { return speedMultipler; }
            set { speedMultipler = value; }
        }

        public BlinkDeferred()
        {
        }

        bool subir = true;
        public override void Update(IObject ent, IList<ILight> lights)
        {
            this.obj = ent;
            if (interpolator >= 1)
            {             
                subir = false;
            }
            else if(interpolator <=0)
            {
                subir = true;
            }

            if (subir)
            {
                interpolator += 1.0f / 60.0f * speedMultipler;
            }
            else
            {
                interpolator -= 1.0f / 60.0f * speedMultipler;
            }

        }
        
        public override void Draw(IModelo modelo, IRenderHelper render, ICamera cam)
        {
            if (obj != null)
            {

                this._shader.Parameters["id"].SetValue(shaderId);
                this._shader.Parameters["specularIntensity"].SetValue(specularIntensity);
                this._shader.Parameters["specularPower"].SetValue(specularPower);
                this._shader.Parameters["finalColor"].SetValue(finalColor.ToVector4());
                this._shader.Parameters["View"].SetValue(cam.View);
                this._shader.Parameters["Projection"].SetValue(cam.Projection);
                this._shader.Parameters["interpolator"].SetValue(interpolator);
                this._shader.Parameters["Texture"].SetValue(modelo.getTexture(TextureType.DIFFUSE));

                 Matrix[] boneTransforms = modelo.getBonesTransformation();
                Matrix wld = obj.getWorldMatrix();
                for (int i = 0; i < modelo.MeshNumber; i++)
                {
                    BatchInformation[] bi = modelo.GetBatchInformation(i);
                    Matrix w1 = Matrix.Multiply(wld, boneTransforms[modelo.GetParentBoneIndex(i)]);
                    this._shader.Parameters["World"].SetValue(w1);                        
                    for (int j = 0; j < bi.Count(); j++)
                    {

                        this._shader.Begin();
                        EngineStuff.GraphicsDevice.VertexDeclaration = bi[j].VertexDeclaration;
                        EngineStuff.GraphicsDevice.Vertices[0].SetSource(modelo.GetVertexBuffer(i), bi[j].StreamOffset, bi[j].VertexStride);
                        EngineStuff.GraphicsDevice.Indices = modelo.GetIndexBuffer(i);

                        this._shader.CurrentTechnique.Passes[0].Begin();
                        EngineStuff.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, bi[j].BaseVertex, 0, bi[j].NumVertices, bi[j].StartIndex, bi[j].PrimitiveCount);
                        this._shader.CurrentTechnique.Passes[0].End();
                        this._shader.End();
                    }

                }            
            }

        }
        public override void Initialize()
        {
            base.Initialize();
            this._shader = EngineStuff.InternalContentManager.GetAsset<Effect>("BlinkGBuffer");
        }
    }
}
